﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Compilex.BaseLibrary;
using Compilex.Automata;
using System.Diagnostics;
using Compilex.Lexer.Automata;

namespace Compilex.Automata
{
    public class TokenRecognizerBuilder
    {
        private LanguageConfiguration language;
        public SimpleList<TokenRecognizer> TokenRecognizers { get; private set; }
        public TokenRecognizerBuilder(LanguageConfiguration language)
        {
            this.language = language;
            this.TokenRecognizers = new SimpleList<TokenRecognizer>();
            BuildRecognizersInOrder(language.operators);
        }

        private void BuildRecognizersInOrder(Operator[] operators)
        {
            TokenRecognizers.Add(BuildCommentsRecognizer());
            TokenRecognizers.Add(BuildWhiteSpaceRecognizer());
            TokenRecognizers.Add(BuildIdentifierRecognizer());
            TokenRecognizers.Add(BuildIntegerRecognizer());
            TokenRecognizers.Add(BuildFloatRecognizer());
            TokenRecognizers.Add(BuildLiteralRecognizer());
            TokenRecognizers.Add(BuildCaracterRecognizer());
            TokenRecognizers.AddRange(BuildOperatorsRecognizers(operators));
        }

        private SimpleList<TokenRecognizer> BuildOperatorsRecognizers(Operator[] operators)
        {
            SimpleList<TokenRecognizer> operatorRecognizers = new SimpleList<TokenRecognizer>();
            foreach (Operator op in operators)
            {
                operatorRecognizers.Add(new OperatorTokenRecognizer(op));
            }
            return operatorRecognizers;
        }

        private TokenRecognizer BuildLiteralRecognizer()
        {
            return new TokenRecognizer(new LiteralDFA(),
                delegate(SimpleHashtable<string, WordToken> o, string input)
                {
                    if (input.StartsWith("\""))
                        input = input.Substring(1);
                    if (input.EndsWith("\""))
                        input = input.Substring(0, input.Length - 1);

                    return new LiteralToken(input);
                });
        }

        private TokenRecognizer BuildCaracterRecognizer()
        {
            return new TokenRecognizer(new CaracterDFA(),
                delegate(SimpleHashtable<string, WordToken> o, string input)
                {
                    if (input.StartsWith("'"))
                        input = input.Substring(1);
                    if (input.EndsWith("'"))
                        input = input.Substring(0, input.Length - 1);

                    return new CaracterToken(input);
                });
        }


        private TokenRecognizer BuildFloatRecognizer()
        {
            return new TokenRecognizer(new FloatDFA(),
                delegate(SimpleHashtable<string, WordToken> o, string input)
                {
                    return new FloatToken(StringUtils.ParseFloat(input));
                });
        }

        private TokenRecognizer BuildIntegerRecognizer()
        {
            return new TokenRecognizer(new PositiveIntegerDFA(),
                delegate(SimpleHashtable<string, WordToken> o, string input)
                {
                    return new IntToken(StringUtils.ParseInt(input));
                });
        }

        private TokenRecognizer BuildIdentifierRecognizer()
        {
            return new TokenRecognizer(new IdentifierDFA(),
                delegate(SimpleHashtable<string, WordToken> words, string identifier)
                {
                    if (!words.ContainsKey(identifier))
                    {
                        words.Add(identifier, new IdentifierToken(identifier));
                    }
                    return words[identifier];
                });
        }

        private TokenRecognizer BuildWhiteSpaceRecognizer()
        {
            return new TokenRecognizer(new WhiteSpaceDFA(),
                delegate(SimpleHashtable<string, WordToken> o, string input)
                {
                    return null;
                });
        }

        private TokenRecognizer BuildCommentsRecognizer()
        {
            return new TokenRecognizer(new CommentsDFA(),
                delegate(SimpleHashtable<string, WordToken> o, string input)
                {
                    return null;
                });
        }
    }
}
